/**
 * Copyright 2006 gworks.com.au
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. (http://www.apache.org/licenses/LICENSE-2.0)
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for 
 * the specific language governing permissions and limitations under the License.
 *
 * <dhamma-message src="Atisha (11th century Tibetan Buddhist master)">
 * 	The greatest achievement is selflessness. The greatest worth is self-mastery.
 * 	The greatest quality is seeking to serve others. The greatest precept is continual awareness.
 * 	The greatest medicine is the emptiness of everything. The greatest action is not conforming with the worlds ways.
 * 	The greatest magic is transmuting the passions. The greatest generosity is non-attachment.
 * 	The greatest goodness is a peaceful mind. The greatest patience is humility.
 * 	The greatest effort is not concerned with results. The greatest meditation is a mind that lets go.
 * 	The greatest wisdom is seeing through appearances. 
 * </dhamma-message>
 */
package org.javaongems.client.winctrls;

import java.util.ArrayList;

import org.javaongems.client.rt.text.dom.DomExtUtils;
import org.javaongems.client.rt.text.dom.UiObjectExtUtils;


import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.SourcesTableEvents;
import com.google.gwt.user.client.ui.TableListener;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.Widget;

/**
 * <p>Provides a representation of the list view in detailed mode.</p>
 * 
 * @author Ashin Wimalajeewa (ash)
 */
public class ListViewDetailView extends Grid implements ListViewDataSourceView, TableListener {
		private final ListView container;
		private Element tHeadElem, tHeadTrElem;
		private int columnSize = -1;
		private Element lastSortedCol, nextSortedCol;
		
		/*pkg*/ ListViewColumnHeaderFormatter headerFormatter;
		/*pkg*/ ListViewDetailViewStyle  formatStyler;

		public ListViewDetailView(ListView view) {
			super();
			container = view;
			injectColumnHeader();
			UIObject.setStyleName(this.getElement(), "gems-ListView", true);
			UIObject.setStyleName(getBodyElement(), "gems-ListViewScrollContent", true);
			addTableListener(this);
			sinkEvents(Event.ONDBLCLICK);
		}
		
		public void onBrowserEvent(Event event) {
		    switch (DOM.eventGetType(event)) {
		      case Event.ONCLICK: {
		    	  container.lastEvent = event;
		    	  Element th = DomExtUtils.getEventTargetTag(event, getElement(), "th");
		    	  if (th != null) {
		    		  nextSortedCol = th;
		              Element tr = DOM.getParent(th);
		              int column = DOM.getChildIndex(tr, th);
		              if (column == container.comparisonColumn)
		            	  container.comparator.descOrder = !container.comparator.descOrder;
		              else {
		            	  container.comparisonColumn = column;
		            	  container.comparator.descOrder = false;
		              }
		              render();
		              DOM.eventCancelBubble(event, true);
		    		  return;
		    	  }
		    	  break;
		      } 
		      case Event.ONDBLCLICK: {
	    		  if (container.eventHandler != null) {
	    			  Element td = DomExtUtils.getEventTargetTag(event, getElement(), "td");
	    			  if (td != null) {
	    				  int[] rowCol = getRowColInfo(td);
		    			  container.eventHandler.onDblClick(container, container.sortedRows[rowCol[0]], rowCol[1]);
		    		  }
		    	  }		    	  
		    	  break;
		      }
		    }
		    super.onBrowserEvent(event);
		}
		  
		public void onCellClicked(SourcesTableEvents sender, int row, int cell) {
			int id = container.sortedRows[row];
			container.handleDataRowSelection(id, row);
			if (container.eventHandler != null)
				container.eventHandler.onClick(container, id, cell);
		}

		public void render() {
			int rowSz = container.source.getDataRowCount();
			int colSz = container.source.getColCount();
			resize(rowSz, colSz);		
			container.sortData(rowSz);
//			GOOGLE_BUG_correctGridSize();	// google's grid has screwed me here
			renderHeader(colSz);
			renderData(rowSz, colSz);
			renderHeaderAnnotations();
			renderSelections();
		}
		
		public void renderSelections() {
			renderSelection(container.deSelectedIds, false);
			renderSelection(container.selectedIds, true);
		}
		
		public void resize(int rowSz, int colSz) {
			container.prepareSortMappers(rowSz);
			super.resize(rowSz + 1, colSz); // allocate for header aswell
		}

		public Widget toWidget() {
			return this;
		}
		
		private int[] getRowColInfo(Element td) {
			int[] ret = new int[2];
			Element tr = DOM.getParent(td);
			ret[0] = DOM.getChildIndex(getBodyElement(), tr);
			ret[1] = DOM.getChildIndex(tr, td);
			return ret;
		}

		private void renderData(int rowSz, int colSz) {
			CellFormatter cfmtr = getCellFormatter();
			RowFormatter rfmtr = getRowFormatter();
			for (int i = 0; i < rowSz; i++) {
				if (formatStyler != null)
					formatStyler.styleRow(container.sortedRows, container.dataSrcRows, i, rfmtr);
				for (int j = 0; j < colSz; j++) {
					String clz = (j == container.comparisonColumn ? "sortCol": "");
					cfmtr.setStyleName(i, j, clz);
					cfmtr.addStyleName(i, j, "gwt-HTML");
					String html = container.source.getDisplayCellData(container.sortedRows[i], j);
					setHTML(i+1, j, html);
					cfmtr.setHeight(i+1, j, "20px");
					if (formatStyler != null)
						formatStyler.styleCell(container.sortedRows, container.dataSrcRows, i+1, j, cfmtr);
				}
			}
		}
		
		private void renderSelection(ArrayList list, boolean select) {
			CellFormatter fmtr = getCellFormatter();
			int sz = list.size();
			boolean isCompCol = (container.comparisonColumn == 0);
			for (int i = 0; i < sz; i++) {
				Integer id = (Integer) list.get(i);
				int sortedRow = container.dataSrcRows[id.intValue()];
				Element elm = fmtr.getElement(sortedRow, 0);
				String newClz = (select ? "selected" :(isCompCol ? "sortCol": ""));
				DOM.setAttribute(elm, "className", newClz);
				UiObjectExtUtils.setStyleName(elm, "gwt-HTML", true);
			}
		}

		private void renderHeaderAnnotations() {
			DOM.setAttribute(lastSortedCol, "className", "");
			UiObjectExtUtils.setStyleName(lastSortedCol, "gwt-HTML", true);
			if (nextSortedCol == null)
				nextSortedCol = lastSortedCol;
			DOM.setAttribute(nextSortedCol, "className", (container.comparator.descOrder ? "desc": "asc"));
			UiObjectExtUtils.setStyleName(nextSortedCol, "gwt-HTML", true);
			lastSortedCol = nextSortedCol;
		}
		
		private void renderHeader(int sz) {
		    for (int i = 0; i < sz; i++) {
				Element hdElem;
				boolean create = columnSize != sz;
				if (create) {
					hdElem = DOM.createTH();
					DOM.insertChild(tHeadTrElem, hdElem, i);
				} else
					hdElem = DOM.getChild(tHeadTrElem, i);
				if (lastSortedCol == null)
					lastSortedCol = hdElem;
				String dispName = container.source.getColumnDisplayName(i);
				DOM.setInnerHTML(hdElem, dispName);
				headerFormatter.setHeight(i, "22px");
				headerFormatter.addStyleName(i, "gwt-HTML");
				if (formatStyler != null)
					formatStyler.styleHeader(i, headerFormatter);
			}
		    columnSize = sz;
		}

		private void injectColumnHeader() {
			tHeadElem = DOM.createElement("thead");
		    Element tableElem = getElement();
		    DOM.insertChild(tableElem, tHeadElem, 0);
		    tHeadTrElem = DOM.createTR();
		    DOM.appendChild(tHeadElem, tHeadTrElem);
		    headerFormatter = new ListViewColumnHeaderFormatter(tHeadElem);
		}
		
		private void GOOGLE_BUG_correctGridSize() {
			Element body = getBodyElement();
			DOM.removeChild(body, DOM.getChild(body, 0));
		}
	}